1 using System;
2 using UnityEngine;
3 using UnityEngine.Assertions;
4
5 namespace ProceduralToolkit.Examples
6 {
7 /// <summary>
8 /// A procedural chair generator
9 /// </summary>
10 public static class ChairGenerator
11 {
12 [Serializable]
13 public class Config
14 {
15 public float legWidth = 0.07f;
16 public float legHeight = 0.7f;
17 public float seatWidth = 0.7f;
18 public float seatDepth = 0.7f;
19 public float seatHeight = 0.05f;
20 public float backHeight = 0.8f;
21 public bool hasStretchers = true;
22 public bool hasArmrests = false;
23 public Color color = Color.white;
24 }
25
26 private delegate MeshDraft StretchersConstructor(Vector3[] legCenters, float legWidth, float legHeight);
27
28 private static readonly StretchersConstructor[] stretchersConstructors =
29 {
30 Stretchers.XStretchers,
31 Stretchers.HStretchers,
32 Stretchers.BoxStretchers
33 };
34
35 private delegate MeshDraft BackConstructor(Vector3 center, float width, float length, float height);
36
37 private static readonly BackConstructor[] backConstructors =
38 {
39 Backs.Back0,
40 Backs.Back1,
41 Backs.RodBack
42 };
43
44 private delegate MeshDraft ArmrestsConstructor(float seatWidth, float seatDepth, Vector3 backCenter,
45 float backHeight, float legWidth);
46
47 private static readonly ArmrestsConstructor[] armrestsConstructors =
48 {
49 Armrests.Armrests0,
50 Armrests.Armrests1
51 };
52
53 public static MeshDraft Chair(Config config)
54 {
55 Assert.IsTrue(config.legWidth > 0);
56 Assert.IsTrue(config.legHeight > 0);
57 Assert.IsTrue(config.seatWidth > 0);
58 Assert.IsTrue(config.seatDepth > 0);
59 Assert.IsTrue(config.seatHeight > 0);
60 Assert.IsTrue(config.backHeight > 0);
61
62 Vector3 right = Vector3.right*(config.seatWidth - config.legWidth)/2;
63 Vector3 forward = Vector3.forward*(config.seatDepth - config.legWidth)/2;
64
65 var chair = new MeshDraft {name = "Chair"};
66
67 // Generate legs
68 var legCenters = new Vector3[]
69 {
70 -right - forward,
71 right - forward,
72 right + forward,
73 -right + forward
74 };
75 chair.Add(Leg0(legCenters[0], config.legWidth, config.legHeight));
76 chair.Add(Leg0(legCenters[1], config.legWidth, config.legHeight));
77 chair.Add(Leg0(legCenters[2], config.legWidth, config.legHeight));
78 chair.Add(Leg0(legCenters[3], config.legWidth, config.legHeight));
79
80 // Generate stretchers
81 if (config.hasStretchers)
82 {
83 var stretchersConstructor = stretchersConstructors.GetRandom();
84 chair.Add(stretchersConstructor(legCenters, config.legWidth, config.legHeight));
85 }
86
87 // Generate seat
88 chair.Add(Seat0(Vector3.up*config.legHeight, config.seatWidth, config.seatDepth, config.seatHeight));
89
90 // Generate chair back
91 Vector3 backCenter = Vector3.up*(config.legHeight + config.seatHeight) +
92 Vector3.forward*(config.seatDepth - config.legWidth)/2;
93 var backConstructor = backConstructors.GetRandom();
94 chair.Add(backConstructor(backCenter, config.seatWidth, config.legWidth, config.backHeight));
95
96 // Generate armrests
97 if (config.hasArmrests)
98 {
99 var armrestsConstructor = armrestsConstructors.GetRandom();
100 chair.Add(armrestsConstructor(config.seatWidth, config.seatDepth, backCenter, config.backHeight,
101 config.legWidth));
102 }
103
104 chair.Paint(config.color);
105
106 return chair;
107 }
108
109 private static MeshDraft Leg0(Vector3 center, float width, float height)
110 {
111 var draft = MeshDraft.Hexahedron(width, width, height);
112 draft.Move(center + Vector3.up*height/2);
113 return draft;
114 }
115
116 private static MeshDraft Seat0(Vector3 center, float width, float length, float height)
117 {
118 var draft = MeshDraft.Hexahedron(width, length, height);
119 draft.Move(center + Vector3.up*height/2);
120 return draft;
121 }
122
123 public static MeshDraft BeamDraft(Vector3 from, Vector3 to, float width, float rotation = 0)
124 {
125 var up = to - from;
126 var draft = MeshDraft.Hexahedron(width, width, up.magnitude);
127 Vector3 direction = up;
128 direction.y = 0;
129 var quaternion = Quaternion.identity;
130 if (direction != Vector3.zero)
131 {
132 quaternion = Quaternion.LookRotation(direction);
133 }
134 draft.Rotate(Quaternion.FromToRotation(Vector3.up, up)*Quaternion.Euler(0, rotation, 0)*quaternion);
135 draft.Move((from + to)/2);
136 return draft;
137 }
138 }
139 }